/**
 * SPDX-FileCopyrightText: 2023-2025 Sangfor Technologies Inc.
 * SPDX-License-Identifier: Mulan PSL v2
 */
/* eslint-disable */
// TODO: remove nocheck add types
// @ts-nocheck
/**
 * Created by hjh on 2018/5/15.
 */

import { isObject, isString, isFunction } from './typeof';
import Vue from 'vue';

let vm = new Vue();

function trim (string) {
    return string.replace(/(^\s*)|(\s*$)/g, '');
}

function trimCRLF (str) {
    return str.replace(/^[\r\n]*|[\r\n]*$]/, '');
}

function shiftTab (str) {
    let lines = str.split(/\r?\n/g);
    let spaceCnt = Math.min(...lines.map(line => {
        return line.indexOf(line.replace(/^\s*/, ''));
    }));
    return lines.map(line => {
        return line.slice(spaceCnt);
    }).join('\n');
}

function getTemplate (content = '') {
    const REG = /<template>((.|\r|\n)*)<\/template>/;
    let match = content.match(REG);

    return shiftTab(trimCRLF((match && match[1] || '').trimRight()));
}

function getScript (content = '') {
    const REG = /<script>((.|\r|\n)*)<\/script>/;
    let match = content.match(REG);

    return shiftTab(trimCRLF((match && match[1] || '').trimRight()));
}

function getCSS (content = '') {
    const REG = /<style.*>((.|\r|\n)*)<\/style>/;
    let match = content.match(REG);

    return shiftTab(trimCRLF((match && match[1] || '').trimRight()));
}

function updateCSS (css = '', isStylus = false) {
    let styleEl = document.createElement('style');

    css = trim(css);

    if (!isStylus) {
        styleEl.textContent += css;
        document.head.appendChild(styleEl);
        return;
    }

    window.stylus(css).render((err, css) => {
        styleEl.textContent += css;
        document.head.appendChild(styleEl);
    });
}

function transformES6 (code) {
    return window.Babel.transform(code, {
        presets: ['es2015', 'stage-0']
    }).code;
}

/* eslint-disable */
function fetchScriptObject (script) {
    if (!script) {
        return 'javascript 语法错误';
    }

    // 干掉注释
    script = script.replace(/(\/\/.*)|(\/\*\*[\s\S]*?\*\/)/g, '');

    let importVueReg = /import\s+(\w+)\s+from\s+\'([\S]+\.vue)\'\s*;?/;
    let importJSReg = /import\s+(\w+)\s+from\s+\'([\S]+\.js)\'\s*;?/;
    let vueSrcMatchs = script.match(new RegExp(importVueReg, 'g'));
    let jsSrcMatchs = script.match(new RegExp(importJSReg, 'g'));

    let vueSrcList = [];
    let jsSrcList = [];

    if (vueSrcMatchs && vueSrcMatchs.length) {
        vueSrcList = vueSrcMatchs.map(match => JSON.parse(match.replace(importVueReg, '{"name":"$1","path":"$2"}')));
    }

    if (jsSrcMatchs && jsSrcMatchs.length) {
        jsSrcList = jsSrcMatchs.map(match => JSON.parse(match.replace(importJSReg, '{"name":"$1","path":"$2"}')));
    }

    // 转换输出
    script = script.replace(/export( default)?/, 'return');
    script = script.replace(new RegExp(importVueReg, 'g'), '');
    script = script.replace(new RegExp(importJSReg, 'g'), '');

    let vuePromise;
    let srcNameList = vueSrcList.concat(jsSrcList).map(o => o.name);

    if (!vueSrcList.length && !jsSrcList.length) {
        try {
            eval(
                transformES6(
                    `vuePromise = Promise.resolve().then(function(){
                        ${script}
                    })`,
                    {presets: ['es2015', 'stage-0']}
                )
            );
        } catch (e) {
            return `以下代码中出现错误：\n ${script}`
        }

    } else {
        try {
            eval(
                transformES6(
                    `vuePromise = Promise.all([
                        ${[
                            ...vueSrcList.map(o => 'fetchVueObject("' + o.path + '")'),
                            ...jsSrcList.map(o => 'fetchConfig("' + o.path + '")')
                        ].join(',')}
                    ]).then(function(_results){
                        ${srcNameList.map((name, index) => `var ${name} = _results[${[index]}];`).join('\n')}
                        ${script}
                    })`,
                    {presets: ['es2015', 'stage-0']}
                )
            );
        } catch (e) {
            return `以下代码中出现错误：\n ${script}`
        }

    }

    return vuePromise;
}

// http.get js 静态资源的时候有时候返回字符串，有时候返回 Blob 对象，在这里做下兼容处理
function fetchPath (path) {
    path += `?_t=${new Date().getTime()}`;

    return new Promise(resolve => {
        vm.$http.get(path).then(resp => {
            if (isString(resp.bodyText)) {
                resp.bodyText = Promise.resolve(resp.bodyText);
            }

            // 下面判断是否有 then 方法，而不是 instanceof Promise
            // 原因是打包后在火狐浏览器下 instanceof Promise 会返回 false 从而获取不到
            if (resp.bodyText && isFunction(resp.bodyText.then)) {
                resp.bodyText.then(body => {
                    resolve(body);
                });
            }

            // 请求 vue 文件时会走到这里面去
            if (isObject(resp.bodyText) && resp.bodyText.promise && isFunction(resp.bodyText.promise.then)) {
                resp.bodyText.promise.then(body => {
                    resolve(body);
                });
            }
        }, () => {
            resolve('');
        });
    });
}

function fetchConfig (path) {
    return new Promise(async function (resolve) {
        let body = await fetchPath(path);

        if (!body) {
            resolve('');
            return;
        }

        let scriptConfig = await fetchScriptObject(body);

        if (isString(scriptConfig)) {
            window.console.error('fetchConfig error: ', scriptConfig);

            resolve({});
        } else {
            resolve(scriptConfig);
        }
    });
}

function fetchVueObject (path) {
    return new Promise(async function (resolve) {
        let body = await fetchPath(path);

        if (!body) {
            resolve('');
            return;
        }

        let template = getTemplate(body);
        let script = getScript(body);
        let css = getCSS(body);
        let vueObject = await fetchScriptObject(script);

        if (css) {
            updateCSS(css, /lang=\"stylus\"/.test(body));
        }

        if (isString(vueObject)) {
            window.console.error('fetchVueObject error: ', vueObject);

            resolve({});
        } else {
            resolve(Object.assign({template}, vueObject));
        }
    });
}

export {
    fetchConfig,
    fetchVueObject
};

/* eslint-enable */